package com.example.ymm.modules1.service.dkn;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.tea.TeaException;
import com.example.ymm.util.EmailUtil;
import com.example.ymm.util.RedisKeyManager;
import com.example.ymm.util.RedisUtil;
import com.example.ymm.util.UtilValidate;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 迪卡侬 forecas token 获取工具类
 * @author zeymo
 */
@Slf4j
@Service
public class DknForecastAccessTokenService {

    @Value("${forecast.key}")
    private String apiKey;



    @Value("${forecast.auth}")
    private String auth;//rank2 和这里的 forecas token请求路径是一样的
    @Autowired
    RedisUtil redisUtil;

    private volatile AccessToken accessToken;

    @Getter
    @Setter
    static class AccessToken {
        private String accessToken;
        private Long expireTimestamp;
    }

    /**
     * dkn token有效期约2小时
     * expireIn=7199
     * @return
     */
    private String refreshAccessToken() {

        try {
            JsonNode urlToken = getUrlToken();

            AccessToken accessToken = new AccessToken();
            accessToken.setAccessToken(urlToken.path("access_token").asText());
            accessToken.setExpireTimestamp(System.currentTimeMillis() + urlToken.path("expires_in").asInt()* 1000);
            this.accessToken = accessToken;
//            System.out.println("---urlToken::"+urlToken);
//            log.info("refresh dkn access token success, expireIn="+ urlToken.path("expires_in").asInt());
            return accessToken.getAccessToken();
        } catch (TeaException e) {
            log.error("dkn token 获取异常 " +
                    "TeaException, errCode={}, errorMessage={}", e.getCode(), e.getMessage(), e);
            EmailUtil.sendEmail("1055162826@qq.com","获取 dkn token异常errCode:"+e.getCode(),e.getMessage());

            return null;
        } catch (Exception e) {
            log.error("token 获取异常2", e);
            return null;
        }
    }

    public synchronized String getAccessToken(){
        String getUrlToken=null;
        try{
            String tokenKey = RedisKeyManager.forecast_access_token;
            String lockKey = RedisKeyManager.forecast_access_lock;
            if(!redisUtil.hasKey(tokenKey)){
                boolean isOpen  = redisUtil.setIfAbsent(lockKey,"1",1000L, TimeUnit.SECONDS);
                if(isOpen){
                    getUrlToken=refreshAccessToken();
                    redisUtil.set(tokenKey,getUrlToken,7000L);
                    return getUrlToken;
                }else{
                    //  Thread.sleep(1100L);//休眠等待执行
                    if(!redisUtil.hasKey(tokenKey)){
                        isOpen  = redisUtil.setIfAbsent(lockKey,"1",2L, TimeUnit.SECONDS);
                        if(isOpen){
                            getUrlToken=refreshAccessToken();
                            redisUtil.set(tokenKey,getUrlToken,7000L);
                            return getUrlToken;
                        }else{
                            redisUtil.remove(tokenKey);
                            getUrlToken=refreshAccessToken();
                            redisUtil.set(tokenKey,getUrlToken,7000L);
                            return getUrlToken;
                        }
                    }else{
                        return redisUtil.getString(tokenKey);
                    }
                }
            }else{
                return  redisUtil.getString(tokenKey);
            }
        }catch (Exception e){
            return null;
        }
    }



    public  JsonNode getUrlToken(){
        String url=auth;
        JSONObject heard = new JSONObject();
        heard.put("Authorization", "Basic "+apiKey);
        JSONObject parameter = new JSONObject();
        parameter.put("grant_type", "client_credentials");
        return sendPostDef(url,parameter,heard);
    }

    public JsonNode sendPostDef(String url, JSONObject param,JSONObject header) {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type","application/x-www-form-urlencoded");
        httpPost.addHeader("Accept-Charset","utf-8");
        if(UtilValidate.isNotEmpty(header)){
            header.forEach((k,v)->{
                httpPost.addHeader(k,v.toString());
            });
        }
        String p="";
        StringBuffer buffer=new StringBuffer();
        param.forEach((key,value)->{
            buffer.append(key+"="+value+"&");

        });
        p=buffer.substring(0,buffer.length()-1);
        httpPost.setEntity(new StringEntity(p,"UTF-8"));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        HttpEntity entity = response.getEntity();
        JsonNode jsonNode=null;
        try {
            String content = EntityUtils.toString(entity,"UTF-8");
            System.out.println("---token json:"+ JSONObject.toJSONString(content));
            jsonNode = objectMapper.readTree(content);
        } catch (IOException e) {
            log.error(e.getMessage(),e);
            throw new RuntimeException(e);
        }
        return jsonNode;
    }

    public JsonNode postJson(String url, JSONArray param) {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type","application/json");
        httpPost.addHeader("Accept-Charset","utf-8");
        String accessToken1 = getAccessToken();
        System.out.println("---accessToken1:"+accessToken1);
//        System.out.println(param);
        httpPost.addHeader("Authorization","Bearer "+accessToken1);
        String p=param.toJSONString();

        httpPost.setEntity(new StringEntity(p,"UTF-8"));
        HttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        HttpEntity entity = response.getEntity();
        JsonNode jsonNode=null;
        try {
            if(UtilValidate.isNotEmpty(entity)){
                jsonNode = objectMapper.readTree(EntityUtils.toString(entity));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return jsonNode;
    }


    public JsonNode deleteJson(String url) {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpClient httpClient = HttpClients.createDefault();
        HttpDelete httpDelete = new HttpDelete(url);
        httpDelete.addHeader("Content-Type","application/json");
        httpDelete.addHeader("Accept-Charset","utf-8");
        String accessToken1 = getAccessToken();
        httpDelete.addHeader("Authorization","Bearer "+accessToken1);
        httpDelete.addHeader("x-api-key",apiKey);
//        String p=param.toJSONString();

        HttpResponse response = null;
        try {
            response = httpClient.execute(httpDelete);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        HttpEntity entity = response.getEntity();
        JsonNode jsonNode=null;
        try {
            if(UtilValidate.isNotEmpty(entity)){
                jsonNode = objectMapper.readTree(EntityUtils.toString(entity));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return jsonNode;
    }


    public JsonNode getJson(String url, JSONObject param) {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpClient httpClient = HttpClients.createDefault();
        String p = "";
        HttpResponse response = null;

        if (UtilValidate.isNotEmpty(param)) {
            StringBuffer buffer = new StringBuffer();
            param.forEach((key, value) -> {
                buffer.append(key + "=" +value.toString()  + "&");

            });
            p += "?" + buffer.toString().substring(0, buffer.length()-1);
        }

        try {
            String url_f=url+ p;
//            System.out.println("---url_f::"+url_f);
            HttpGet httpPost = new HttpGet(url_f);
            httpPost.addHeader("Content-Type","application/json");
            httpPost.addHeader("Accept-Charset","utf-8");
            String accessToken1 = getAccessToken();
//            System.out.println(accessToken1);
            httpPost.addHeader("Authorization","Bearer "+accessToken1);
            //  httpPost.setEntity(new StringEntity(p,"UTF-8"));


            response = httpClient.execute(httpPost);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        HttpEntity entity = response.getEntity();
        JsonNode jsonNode=null;
        try {
            if(UtilValidate.isNotEmpty(entity)){
                String content = EntityUtils.toString(entity,"UTF-8");
                jsonNode = objectMapper.readTree(content);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return jsonNode;
    }


}
